﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed
#pragma once

#include "GcmpModelInterface.h"
#include "IElement.h"

namespace gcmp
{
    class ElementId;
    class IElementJoinBehavior;
    enum class JoinType;
    class IMultiJoinData;

    /// \brief 连接数据结构体
    struct GCMP_MODEL_INTERFACE_EXPORT JoinData
    {
        /// \brief 构造JoinData
        ///
        /// \param attachingId    次对象id
        /// \param attachingPos  次对象连接位置
        /// \param attachedId    主对象id
        /// \param attachedPos    主对象连接位置
        JoinData(const ElementId& attachingId, JoinPosition attachingPosition, const ElementId& attachedId, JoinPosition attachedPosition);

        ElementId AttachingElementId;         ///<  次对象id
        JoinPosition   AttachingPosition;     ///<  次对象连接位置
        ElementId AttachedElementId;          ///<  主对象id
        JoinPosition   AttachedPosition;      ///<  主对象连接位置
    };

    /// \brief 连接关系对象
    /// 
    /// 连接关系，即两个构件在几何满足一定条件时，做的相连处理。如墙与墙的T型连接
    class GCMP_MODEL_INTERFACE_EXPORT IElementJoin : public IElement
    {
        DEFINE_CAST_DERIVED(gcmp::IElementJoin, gcmp::IElement);
    public:
        /// \brief 析构函数
        virtual ~IElementJoin() {};

        /// \brief 创建连接关系对象
        /// \param opElementJoinBehavior 连接行为对象
        /// \param joinData   连接数据
        /// \return 连接关系对象
        /// \see JoinData
        static IElementJoin* Create(OwnerPtr<IElementJoinBehavior> opElementJoinBehavior, const JoinData& joinData);

        /// \brief 获取对象连接行为
        /// \return 对象连接行为
        virtual IElementJoinBehavior* GetElementJoinBehavior() = 0;

        /// \brief 获取对象连接行为
        /// \return 对象连接行为
        virtual const IElementJoinBehavior* GetElementJoinBehavior() const = 0;

        /// \brief 获取连接对象的ElementId
        /// \return 连接对象的ElementId
        virtual ElementId GetAttachingId() const = 0;

        /// \brief 设置连接对象的ElementId
        /// \param elementId 连接对象的ElementId
        /// \return void
        virtual void SetAttachingId(const ElementId& elementId) = 0;

        /// \brief 获取被连接对象的ElementId
        /// \return 被连接对象的ElementId
        virtual ElementId GetAttachedId() const = 0;

        /// \brief 设置被连接对象的ElementId
        /// \param elementId 被连接对象的ElementId
        /// \return void
        virtual void SetAttachedId(const ElementId& elementId) = 0;

        /// \brief 获取连接对象的连接位置
        /// \return 连接对象的连接位置
        virtual JoinPosition GetAttachingPosition() const = 0;

        /// \brief 设置连接对象的连接位置
        /// \param position 连接位置
        /// \return 无
        virtual void SetAttachingPosition(const JoinPosition& position) = 0;

        /// \brief 获取被连接对象的连接位置
        /// \return 被连接对象的连接位置
        virtual JoinPosition GetAttachedPosition() const = 0;

        /// \brief 设置被连接对象的连接位置
        /// \param position 连接位置
        /// \return 无
        virtual void SetAttachedPosition(const JoinPosition& position) = 0;

        /// \brief 获取多构件连接数据
        /// 
        /// \return 多构件连接数据
        virtual IMultiJoinData* GetMultiJoinData() = 0;

        /// \brief 获取多构件连接数据
        /// 
        /// \return 多构件连接数据
        virtual const IMultiJoinData* GetMultiJoinData() const = 0;

        /// \brief 反转连接关系（该接口废弃，由业务层实现）
        ///
        /// 目前T形连接不支持反转连接关系
        /// \return 成功返回true，失败返回false
        virtual bool ReverseRelationship_Deprecated() = 0;

        /// \brief 获取MainJoinIdsChanged的关联更新数据标识
        ///
        /// \return 返回ElementJoin的关联更新数据标识
        virtual RegenDataId GetMainJoinIdsChangedRdId() const = 0;

        /// \brief 对MainJoinIdsChanged的变化标记并传播影响
        ///
        /// \return void
        virtual void MarkMainJoinIdsChangedRdId() = 0;

    public:
        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();
    };
}


